package com.Socket;

import java.awt.Button;
import java.awt.Color;
import java.awt.Frame;
import java.awt.Panel;
import java.awt.TextArea;
import java.awt.TextField;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.text.SimpleDateFormat;
import java.util.Date;

public class GUISocket extends Frame {
	// 主窗口宽高
	private int mainWindowWidth;
	private int mainWindowHeight;

	// ip输入框
	private TextField ipTextField;

	// 操作按钮
	private Button sendBtn; // 发送
	private Button clearBtn; // 清空
	private Button logBtn; // 记录
	private Button shakeBtn; // 震动

	// 消息输入框
	private TextArea msgInputTextArea;

	// 消息显示框
	private TextArea msgViewTextArea;

	// 接受socket
	DatagramSocket receiveSocket;

	// 发送socket
	DatagramSocket sendSocket;

	private int bottomPanelH = 40;

	// 构造方法中初始化内容
	public GUISocket() {

	}

	// 带参数的构造方法
	public GUISocket(String title) throws SocketException {
		super(title);
		init();
	}

	// 初始化
	public void init() throws SocketException {
		// 设置主窗口大小和位置
		this.setSize(400, 800);
		this.setLocation(400, 200);

		// 设置主窗口可见
		this.setVisible(true);

		sendSocket = new DatagramSocket();

		mainWindowWidth = this.getSize().width;
		mainWindowHeight = this.getSize().height;

		// 开启接受端
		try {
			receiveMsg();
		} catch (IOException e) {
			System.out.println("接受段错误");
		}

		// 消息显示区域和消息发送区域
		createArea();

		// 操作控件
		createOperation();

		// 关闭主界面
		closeWindow();

		// 添加事件
		addEvent();
	}

	// 添加事件
	private void addEvent() {
		// 发送
		sendBtn.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				sendMsgAction();
			}
		});

		// 回车发送消息
		msgInputTextArea.addKeyListener(new KeyAdapter() {
			@Override
			public void keyReleased(KeyEvent e) {
				if (e.getKeyCode() == KeyEvent.VK_ENTER) {
					sendMsgAction();
				}
			}
		});

		// 清屏
		clearBtn.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				// 保存消息
				try {
					saveMsgLog();
				} catch (IOException e1) {
					// TODO 自动生成的 catch 块
					e1.printStackTrace();
				}

				// 清屏
				msgViewTextArea.setText("");
			}
		});

		// 记录
		logBtn.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent e) {
				try {
					// 保存记录
					saveMsgLog();
					msgViewTextArea.setText("");

					// 读取记录
					readMsgLog();
				} catch (IOException e1) {
					// TODO 自动生成的 catch 块
					e1.printStackTrace();
				}
			}
		});

		// 震动
		shakeBtn.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				try {
					sendMsg(new byte[] { -1 }, getIp());
				} catch (IOException e1) {
					// TODO 自动生成的 catch 块
					e1.printStackTrace();
				}
			}
		});
	}

	// 震动
	private void shakeAction() throws InterruptedException {
		int x = this.getX();
		int y = this.getY();
		int padding = 10;
		long duration = 10;
		this.setLocation(x, y - padding);
		Thread.sleep(duration);
		this.setLocation(x - padding, y);
		Thread.sleep(duration);
		this.setLocation(x, y + padding);
		Thread.sleep(duration);
		this.setLocation(x + padding, y);
		Thread.sleep(duration);
		this.setLocation(x, y);
	}

	// 保存消息
	private void saveMsgLog() throws IOException {
		// 创建缓存文件
		File file = new File("msgLog.txt");
		BufferedWriter writer = new BufferedWriter(new FileWriter(file, true));
		writer.write(msgViewTextArea.getText());
		writer.close();
	}

	// 获取缓存消息
	private void readMsgLog() throws IOException {
		File file = new File("msgLog.txt");
		BufferedReader reader = new BufferedReader(new FileReader(file));
		String line;
		while ((line = reader.readLine()) != null) {
			msgViewTextArea.append(line + "\r\n");
		}
		reader.close();
	}

	// 点击发送或者按回车触发事件
	private void sendMsgAction() {
		String string = msgInputTextArea.getText().trim();
		if (string.length() == 0 || string == null)
			return;

		String sendM = currentTime() + "  我对" + getIp() + "说" + "\r\n" + string + "\r\n" + "\r\n";
		msgViewTextArea.append(sendM);

		// 发送消息
		try {
			sendMsg();
		} catch (IOException e1) {
			e1.printStackTrace();
		}

		// 清空输入框文本
		msgInputTextArea.setText("");
	}

	// 发送指定消息
	private void sendMsg(byte[] bt, String ip) throws IOException {
		DatagramPacket packet = new DatagramPacket(bt, bt.length, InetAddress.getByName(ip), 8888);
		sendSocket.send(packet);
	}

	// 发送消息
	@SuppressWarnings("unused")
	private void sendMsg() throws IOException {
		String mString = msgInputTextArea.getText();
		String ipString = getIp();

		sendMsg(mString.getBytes(), ipString);
	}

	// 接受消息
	private void receiveMsg() throws IOException {
		new Thread() {
			@Override
			public void run() {
				try {
					receiveSocket = new DatagramSocket(8888);
					DatagramPacket packet = new DatagramPacket(new byte[8192], 8192);

					while (true) {
						receiveSocket.receive(packet);
						if (packet.getData()[0] == -1 && packet.getLength() == 1) {
							shakeAction();
							continue;
						}

						String recMsg = new String(packet.getData(), 0, packet.getLength());
						recMsg = currentTime() + " " + packet.getAddress().getHostAddress() + "对我说" + "\r\n" + recMsg
								+ "\r\n" + "\r\n";
						msgViewTextArea.append(recMsg);
					}
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		}.start();
	}

	// 获取当前时间
	private String currentTime() {
		Date now = new Date();
		SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
		return simpleDateFormat.format(now);
	}

	// 消息显示和输入框
	private void createArea() {
		// 消息发送框
		int msgIW = mainWindowWidth;
		int msgIH = 100;
		int msgIY = mainWindowHeight - bottomPanelH - msgIH;
		msgInputTextArea = new TextArea();
		msgInputTextArea.setSize(msgIW, msgIH);
		msgInputTextArea.setLocation(0, msgIY);
		this.add(msgInputTextArea);

		// 消息显示框
		int msgVW = mainWindowWidth;
		int msgVH = mainWindowHeight - bottomPanelH - msgIH - 20;
		msgViewTextArea = new TextArea();
		msgViewTextArea.setLocation(0, 20);
		msgViewTextArea.setSize(msgVW, msgVH);
		msgViewTextArea.setEditable(false);
		this.add(msgViewTextArea);
	}

	// 操作控件
	private void createOperation() {
		int panelH = bottomPanelH;
		Panel panel = new Panel();
		panel.setBackground(new Color(255, 255, 255));
		panel.setSize(mainWindowWidth, panelH);
		panel.setLocation(0, mainWindowHeight - panelH);

		// ip输入框
		int ipTH = panelH - 20;
		ipTextField = new TextField();
		ipTextField.setSize(100, ipTH);
		ipTextField.setLocation(20, 10);
		ipTextField.setText("127.0.0.1");

		// 发送 清屏 记录 震动 四个按钮
		String[] arr = { "发送", "清屏", "记录", "震动" };
		int btnW = (mainWindowWidth - ipTextField.getWidth() - 6 * 20) / arr.length;
		int btnH = ipTextField.getHeight();
		int btnY = ipTextField.getY();
		for (int i = 0; i < arr.length; i++) {
			int btnX = 20 + ipTextField.getWidth() + 20 + (btnW + 20) * i;
			Button button = new Button(arr[i]);
			button.setSize(btnW, btnH);
			button.setLocation(btnX, btnY);

			switch (i) {
			case 0:
				sendBtn = button;
				break;
			case 1:
				clearBtn = button;
				break;
			case 2:
				logBtn = button;
				break;
			case 3:
				shakeBtn = button;
				break;
			default:
				break;
			}

			panel.add(button);
		}

		panel.add(ipTextField);

		this.add(panel);
	}

	// 关闭主界面
	private void closeWindow() {
		this.addWindowListener(new WindowAdapter() {
			@Override
			public void windowClosing(WindowEvent e) {
				receiveSocket.close();
				sendSocket.close();

				// 关闭
				System.exit(0);
			}
		});
	}

	// 获取ip地址
	private String getIp() {
		String ip = ipTextField.getText().trim();
		if (ip.length() == 0) {
			ip = "255.255.255.255";
		}

		return ip;
	}

	// 主方法 入口
	public static void main(String[] args) throws SocketException {
		new GUISocket("聊天");
	}
}
